package net.xiaosaguo.mymall.search.thread;

import lombok.SneakyThrows;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * description: 异步编排
 *
 * @author xiaosaguo
 * @date 2020/07/02
 */
public class CompletableFutureTest {

    public static ExecutorService threadPool = Executors.newFixedThreadPool(10);

    @SneakyThrows
    public static void main(String[] args) {
        System.out.println("main...start...");

        /*
         * 异步运行
         */
        CompletableFuture.runAsync(() -> {
            System.out.println("当前线程01：" + Thread.currentThread().getId());
            int i = 10 / 2;
            System.out.println("运行结果01：" + i);
        }, threadPool);

        /*
         * 感知异常或结果
         */
        CompletableFuture<Integer> completableFuture = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程02：" + Thread.currentThread().getId());
            int i = 10 / 0;
            System.out.println("运行结果02：" + i);
            return i;
        }, threadPool).whenComplete((result, exception) -> {
            // 虽然能得到异常信息，无法修改返回数据
            System.out.println("异步任务成功完成了...,结果是：" + result + ";异常是：" + exception);
        }).exceptionally(throwable -> {
            // 可以感知异常，同时返回默认值
            System.out.println("发生异常：" + throwable);
            return 10;
        });

        Integer integer = completableFuture.get();
        System.out.println("异步结果02：" + integer);

        /*
         * 处理异常或结果
         */
        CompletableFuture<Integer> integerCompletableFuture = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程03：" + Thread.currentThread().getId());
            int i = 10 / 4;
            System.out.println("运行结果03：" + i);
            return i;
        }, threadPool).handle((result, throwable) -> {
            if (result != null) {
                return result * 2;
            }
            if (throwable != null) {
                return 0;
            }
            return 0;
        });

        Integer integer3 = integerCompletableFuture.get();
        System.out.println("异步结果03：" + integer3);

        /*
         * 串行化
         */
        CompletableFuture<Integer> completableFuture04 = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程04：" + Thread.currentThread().getId());
            int i = 10 / 4;
            System.out.println("运行结果04：" + i);
            return i;
        }, threadPool)
                /*.thenRunAsync(() -> {
                    // thenRunAsync 不能获取到上一步的执行结果
                    System.out.println("任务2启动了...");
                }, threadPool);*/
                /*.thenAcceptAsync(result -> {
                    System.out.println("任务2启动了..." + result);
                }, threadPool);*/
                .thenApplyAsync(result -> {
                    System.out.println("任务2启动了..." + result);
                    return result * 2;
                }, threadPool);

        Integer integer4 = completableFuture04.get();
        System.out.println("异步结果04：" + integer4);

        /*
         * 两个任务同时完成，第三个任务开始执行
         */
        CompletableFuture<Object> part1 = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程05：" + Thread.currentThread().getId());
            int i = 10 / 4;
            System.out.println("运行结果05：" + i);
            return i;
        }, threadPool);

        CompletableFuture<Object> part2 = CompletableFuture.supplyAsync(() -> {
            System.out.println("异步执行05：hello");
            return "hello";
        }, threadPool);

        /*
         * 无法感知结果，直接执行第三个任务，第三个任务无返回值
         */
        // part1.runAfterBothAsync(part2, () -> {
        //     System.out.println("异步执行05：第三个任务");
        // }, threadPool);

        /*
         * 接收前两个任务的结果，执行第三个任务，第三个任务无返回值
         */
        // part1.thenAcceptBothAsync(part2, (result1, result2) -> {
        //     System.out.println(result1 + result2);
        // }, threadPool);

        /*
         * 接收前两个任务的结果，执行第三个任务，第三个任务有返回值
         */
        // CompletableFuture<String> part3 = part1.thenCombineAsync(part2, (result1, result2) -> {
        //     return result1 + ":" + result2;
        // }, threadPool);


        /*
         * 两个任务任意一个完成，第三个任务开始执行
         */
        // part1.runAfterEitherAsync(part2, () -> {
        //     System.out.println("...");
        // }, threadPool);

        /*
         * part1 和 part2 返回值类型必须一致
         */
        // part1.acceptEitherAsync(part2,(result)->{
        //     System.out.println(result);
        // } , threadPool);

        // CompletableFuture<String> part3 = part1.applyToEitherAsync(part2, (result) -> {
        //     return result.toString() + "hah";
        // }, threadPool);

        // String result3 = part3.get();
        // System.out.println(result3);


        CompletableFuture<Void> allOf = CompletableFuture.allOf(part1, part2);
        allOf.get();// 等待所有完成
        allOf.join();// 等待所有完成

        CompletableFuture<Object> anyOf = CompletableFuture.anyOf(part1, part2);
        anyOf.get();


        System.out.println("main...end...");
    }
}
